import PocketCastsDataModel
import PocketCastsServer
import PocketCastsUtils
import SwiftUI

class EndOfYear2025StoriesModel: StoryModel {
    static let year = 2025
    var stories = [EndOfYear2025Story]()
    var data = EndOfYear2025StoriesData()

    func indicatorColor(for storyNumber: Int) -> Color {
        if stories.isEmpty || storyNumber >= stories.count || storyNumber < 0 {
            return .white
        }
        switch stories[storyNumber] {
        case .plus, .top5Podcasts:
            return .black
        default:
            return .white
        }
    }

    var primaryBackgroundColor: Color {
        .endOfYear2025Background
    }

    required init() { }

    func populate(with dataManager: DataManager) {
        var stories = [EndOfYear2025Story]()
        // First, search for top 5 podcasts
        let topPodcasts = dataManager.topPodcasts(in: Self.year, limit: 10)

        if !topPodcasts.isEmpty {
            data.top8Podcasts = Array(topPodcasts.suffix(8)).map { $0.podcast }.reversed()
            data.topPodcasts = Array(topPodcasts.prefix(5))
            stories.append(.top5Podcasts)
            stories.append(.topSpot)
        }

        // Listening time
        if let listeningTime = dataManager.listeningTime(in: Self.year),
           listeningTime > 0, !topPodcasts.isEmpty {
            stories.append(.listeningTime)
            data.listeningTime = listeningTime
        }

        // Ratings
        if let ratings = dataManager.summarizedRatings(in: Self.year) {
            data.ratings = ratings
        }
        stories.append(.ratings) // Gets added regardless of the count since we have a fallback empty screen

        // Longest episode
        if let longestEpisode = dataManager.longestEpisode(in: Self.year),
           let podcast = longestEpisode.parentPodcast() {
            data.longestEpisode = longestEpisode
            data.longestEpisodePodcast = podcast
            stories.append(.longestEpisode)

            // Listened podcasts and episodes
            let listenedNumbers = dataManager.listenedNumbers(in: Self.year)
            if listenedNumbers.numberOfEpisodes > 0
                && listenedNumbers.numberOfPodcasts > 0
                && !topPodcasts.isEmpty {
                data.listenedNumbers = listenedNumbers
                stories.append(.numberOfPodcastsAndEpisodesListened)
            }
        }

        stories.append(.plus)

        // Year over year listening time
        let yearOverYearListeningTime = dataManager.yearOverYearListeningTime(in: Self.year)
        if yearOverYearListeningTime.totalPlayedTimeThisYear != 0 ||
            yearOverYearListeningTime.totalPlayedTimeLastYear != 0 {
            data.yearOverYearListeningTime = yearOverYearListeningTime
            stories.append(.yearOverYearListeningTime)
        }

        // Completion Rate
        data.episodesStartedAndCompleted = dataManager.episodesStartedAndCompleted(in: Self.year)
        stories.append(.completionRate)

        self.stories = stories
    }

    private var firstTime = true

    func story(for storyNumber: Int) -> any StoryView {
        defer { firstTime = false }
        switch stories[storyNumber] {
            case .intro:
                return IntroStory2025(afterLoading: FeatureFlag.endOfYearLoadIsFirstStory.enabled && firstTime)
            case .numberOfPodcastsAndEpisodesListened:
                return NumberListened2025(listenedNumbers: data.listenedNumbers, podcasts: data.top8Podcasts)
            case .topSpot:
                return TopSpotStory2025(topPodcast: data.topPodcasts.first!)
            case .top5Podcasts:
                return Top5Podcasts2025Story(top5Podcasts: data.topPodcasts)
            case .ratings:
                return Ratings2025Story(ratings: data.ratings)
            case .listeningTime:
                return ListeningTime2025Story(listeningTime: data.listeningTime)
            case .longestEpisode:
                return LongestEpisode2025Story(episode: data.longestEpisode, podcast: data.longestEpisodePodcast)
            case .yearOverYearListeningTime:
                return YearOverYearCompare2025Story(subscriptionTier: SubscriptionHelper.activeTier, listeningTime: data.yearOverYearListeningTime)
            case .completionRate:
                return CompletionRate2025Story(subscriptionTier: SubscriptionHelper.activeTier, startedAndCompleted: data.episodesStartedAndCompleted)
            case .epilogue:
                return EpilogueStory2025()
            case .plus:
                return PaidStoryWallView2025(subscriptionTier: SubscriptionHelper.activeTier)
        }
    }

    func isInteractiveView(for storyNumber: Int) -> Bool {
        switch stories[storyNumber] {
            case .epilogue, .plus, .top5Podcasts:
                return true
            case .ratings:
                return data.ratings.isEmpty
            default:
                return false
        }
    }

    func shouldLoadData(in dataManager: DataManager) -> Bool {
        // Load data if our `ratings` property is empty
        // Other data is handled in `EndOfYearStoriesBuilder`
        dataManager.ratings.ratings == nil
    }

    func isReady() -> Bool {
        if stories.isEmpty {
            return false
        }

        stories.append(.intro)
        stories.append(.epilogue)

        stories.sortByCaseIterableIndex()

        return true
    }

    var numberOfStories: Int {
        stories.count
    }

    func paywallView() -> AnyView {
        AnyView(PaidStoryWallView2025(subscriptionTier: SubscriptionHelper.activeTier))
    }

    func overlaidShareView() -> AnyView? {
        nil
    }

    func footerShareView() -> AnyView? {
        AnyView(shareView())
    }

    func sharingSnapshotModifier(_ view: AnyView) -> AnyView {
        AnyView(view
            .safeAreaInset(edge: .bottom) {
                Image("logo_pill")
                    .resizable()
                    .frame(width: 153, height: 36)
                    .padding(.top, 16)
                    .padding(.bottom, StoryLogoView.Constants.paddingBottom)
            })
    }

    @ViewBuilder func shareView() -> some View {
        Button(action: {
            StoriesController.shared.share()
        }, label: {
            HStack(alignment: .center, spacing: 8) {
                Image("podcast-share")
                    .resizable()
                    .frame(width: 20, height: 20)
                    .foregroundStyle(.white)
            }
            .padding(0)
            .frame(width: 34, height: 34, alignment: .center)
            .background(.black.opacity(0.44))
            .cornerRadius(90)
        })
        .padding(.horizontal, 24)
        .padding(.vertical, 6)
    }
}


/// An entity that holds data to present EoY 2025 stories
class EndOfYear2025StoriesData {
    var topPodcasts: [TopPodcast] = []

    var listeningTime: Double = 0

    var longestEpisode: Episode!

    var longestEpisodePodcast: Podcast!

    var listenedNumbers: ListenedNumbers!

    var top8Podcasts: [Podcast] = []

    var episodesStartedAndCompleted: EpisodesStartedAndCompleted!

    var yearOverYearListeningTime: YearOverYearListeningTime!

    var ratings: [UInt32: Int] = [:]
}
